package roborally.Pieces;

import be.kuleuven.cs.som.annotate.*;

/**
 * This is a class representing a Game Piece with an Orientation, like a Robot.
 * @version 3.0
 * @author 	Bart Opsomer 2de Bachelor Ingenieurswetenschappen Electrotechniek-Computerwetenschappen 
 * 		   	Peter Opsomer 1ste Master Wiskundige IngenieursTechnieken
 */
public abstract class GamePieceWithOrientation extends GamePiece {
	// the PositionWithOrientation of this GamePieceWithOrientation
	protected PositionWithOrientation positionWithOrientation;
	/**
	 * Creates a GamePieceWithOrientation without a PositionWithOrientation
	 * @effect| super()
	 * @post  | new.getPositionWithOrientation() == null
	 */
	@Raw @Model
	protected GamePieceWithOrientation() {
		super();
		positionWithOrientation = null;
	}
	/**
	 * @return 	the Position (without orientation) of this GamePieceWithOrientation
	 */
	@Override
	public Position getPosition(){
		if(this.positionWithOrientation == null)
			return null;
		return positionWithOrientation.getPosition();
	}
	/**
	 * @return the Position with orientation of this GamePieceWithOrientation
	 */
	@Basic
	public PositionWithOrientation getPositionWithOrientation() {
		return this.positionWithOrientation;
	}
	/**
	 * @return 	the Orientation of this GamePieceWithOrientation
	 * 			| result.equals(getPositionWithOrientation().getOrientation() )
	 * @throws 	NullPointerException
	 * 			the positionWithOrientation is not effective
	 * 			| this.getPositionWithOrientation() == null
	 */
	public Orientation getOrientation() throws NullPointerException {
		return positionWithOrientation.getOrientation();
	}
	/**
	 * Should be used with care: no other classes should directly set the position, but this method is needed in 
	 * Facade.createRobot, Board.addRobot and Board.removeRobot so this method cannot be protected or package 
	 * accessible. If the given Position is null, then the GamePieceWithOrientation is moved off the Board, 
	 * but the Board should be notified. No IllegalArgumentException has to be thrown if !isValidPosition(
	 * positionWithOrientation.getPosition() ) because a MoveOutOfBoardException is already thrown when
	 * making an invalid Position.
	 * 
	 * @param 	positionWithOrientation the new PositionWithOrientation of this GamePieceWithOrientation, may be null
	 * @post 	| new.getPositionWithOrientation() == positionWithOrientation
	 */
	@Raw
	public void setPositionWithOrientation(PositionWithOrientation positionWithOrientation) {
		this.positionWithOrientation = positionWithOrientation;
	}
	/**
	 * Return a String to be added to the toString()-methods of subclasses. This method is not abstract, but subclasses should overwrite this
	 * method to get a representative name for them in the GUI. This method just gives info about the orientation and position of the GamePieceWithOrientation.
	 * 
	 * @return | if(getPositionWithOrientation() == null) then
	 * 		   |	result.endsWith(super.toString() )
	 * 		   | else
	 * 		   |	result.endsWith(" facing " + getOrientation().toString() + super.toString() )
	 */
	public String toString(){
		if(positionWithOrientation == null) {
			return super.toString();
		}
		return " facing " + positionWithOrientation.getOrientation().toString() + super.toString() ;
	}
}
